(* this is a scanner for an extended version of SLP
   we have added booleans, and an if-then-else statement *)

(* User Declarations *)

type pos = int
type lexresult = Tokens.token

val lineNum = ErrorMsg.lineNum
val linePos = ErrorMsg.linePos
fun err (p1, p2) = ErrorMsg.error p1
		   
fun eof () = let val pos = hd(!linePos)
	     in Tokens.EOF(pos, pos)
	     end
%%
nonzero=[1-9];
digit=[0-9];
alpha=[a-zA-Z];
alphanum=[a-zA-Z0-9];
white=[ \t\v\r];

%%
\n	=> ( lineNum := !lineNum+1
	   ; linePos := yypos :: !linePos
	   ; continue()
	   );

{white}	=> (continue());

"print"	=> (Tokens.PRINT(yypos, yypos + size yytext));
"if"	=> (Tokens.IF(yypos, yypos + size yytext));
"then"	=> (Tokens.THEN(yypos,yypos + size yytext));
"else"	=> (Tokens.ELSE(yypos,yypos + size yytext));

"/"	=> (Tokens.DIVIDE(yypos, yypos + size yytext));
"\*"	=> (Tokens.TIMES(yypos, yypos + size yytext));
"-"	=> (Tokens.MINUS(yypos, yypos + size yytext));
"\+"	=> (Tokens.PLUS(yypos, yypos + size yytext));

"<="	=> (Tokens.LESSEQUAL(yypos, yypos + size yytext));
"<"	=> (Tokens.LESS(yypos, yypos + size yytext));
"<="	=> (Tokens.GREATEREQUAL(yypos, yypos + size yytext));
">"	=> (Tokens.GREATER(yypos, yypos + size yytext));
"="	=> (Tokens.EQUAL(yypos, yypos + size yytext));


"("	=> (Tokens.LPAREN(yypos, yypos + size yytext));
")"	=> (Tokens.RPAREN(yypos, yypos + size yytext));

":="	=> (Tokens.COLONEQ(yypos, yypos + size yytext));
";"	=> (Tokens.SEMICOLON(yypos, yypos + size yytext));
","	=> (Tokens.COMMA(yypos, yypos + size yytext));

"true"	=> (Tokens.BOOL(true, yypos, yypos + size yytext));
"false"	=> (Tokens.BOOL(false, yypos, yypos + size yytext));

"0"	=> (Tokens.INT(0, yypos, yypos + size yytext));

({nonzero}{digit}*)	=> (case Int.fromString yytext
			     of NONE => ( ErrorMsg.error yypos ("number not integer " ^ yytext)
					; continue()
					)
			      | SOME z => Tokens.INT(z, yypos, yypos + size yytext));
 
({alpha}{alphanum}*)	=> (Tokens.ID(yytext, yypos, yypos + size yytext));

.	=> ( ErrorMsg.error yypos ("illegal character " ^ yytext)
	   ; continue()
	   );
